package com.keyin.android.net;

import java.util.Vector;
import java.util.concurrent.ThreadPoolExecutor;

public class RunnableWrapper implements Runnable {
	private static final Object THREADPOOL_LOCK = new Object();
	private static Vector<Runnable> threadPool = new Vector<Runnable>();

	private static int threadCount = 0;
	private static int maxThreadCount = 3;
	private static int availableThreads = 0;

	private boolean done = false;

	private int type;
	private RuntimeException err;
	private Runnable internal;

	public RunnableWrapper(Runnable internal, int type) {
		this.internal = internal;
		this.type = type;
	}

	public RuntimeException getErr() {
		return err;
	}

	public void setDone(boolean done) {
		this.done = done;
	}

	public boolean isDone() {
		return done;
	}

	public void run() {
		switch (type) {
		case INTERNAL:
			internal.run();
			break;
		case PUSH_THREAD:
			while (true) {
				Runnable r = null;
				synchronized (THREADPOOL_LOCK) {
					if (threadPool.size() > 0) {
						r = (Runnable) threadPool.elementAt(0);
						threadPool.removeElementAt(0);
					} else {
						try {
							availableThreads++;
							THREADPOOL_LOCK.wait();
							availableThreads--;
						} catch (InterruptedException ex) {
							ex.printStackTrace();
						}
					}
				}
				if (r != null) {
					r.run();
				}
			}
		}
	}

	static void pushToThreadPool(Runnable r) { 
		if (availableThreads == 0 && threadCount < maxThreadCount) {
			threadCount++;
			Thread poolThread = new Thread(new RunnableWrapper(null,
					PUSH_THREAD), "invokeAndBlock" + threadCount);
			poolThread.start();
		}
		synchronized (THREADPOOL_LOCK) {
			threadPool.addElement(r);
			THREADPOOL_LOCK.notify();
		}
	}

	public static final int PUSH_THREAD = 0;
	public static final int INTERNAL = 1;
}
